package org.alma.opengl

import java.io.File
import java.awt.Point
import java.nio.{ByteBuffer, ByteOrder}
import javax.imageio._
import java.awt.geom.AffineTransform
import java.awt.image._
import java.awt.color._
import sun.awt.image.ByteInterleavedRaster

object Texture
{
  def apply(path: File) = new Texture(path)
}

class Texture(val path: File)
{ 
  private val info =
  {
    var temp = ImageIO.read(path)
    val w = temp.getWidth
    val h = temp.getHeight
    val bpp = if (temp.getColorModel.hasAlpha) 4 else 3
    val opacity = if (bpp == 4) java.awt.Transparency.TRANSLUCENT else java.awt.Transparency.OPAQUE
    
    val colorModel = new ComponentColorModel(
      ColorSpace.getInstance(ColorSpace.CS_sRGB), 
      Array(8, 8, 8, 8), 
      if (bpp == 3) false else true, 
      false, 
      opacity,
      DataBuffer.TYPE_BYTE
    )
    
    val raster = LousyScalaCompilerRasterAlternative.create(w, h, bpp == 4)
    val flipped = new BufferedImage(colorModel, raster, false, null)
    val g = flipped.createGraphics
    val gt = new AffineTransform
    
    gt.translate(0, h)
    gt.scale(1, -1d)
    g.transform(gt)
    
    g.drawImage(temp, null, null)
    val data = raster.getDataBuffer.asInstanceOf[DataBufferByte].getData
    g.dispose
    
    val byteBuffer = ByteBuffer.allocateDirect(data.length)
    byteBuffer.order(ByteOrder.nativeOrder)
    byteBuffer.put(data, 0, data.length)
    
    byteBuffer.rewind
    
    (w, h, bpp, byteBuffer)
  }
  
  val width = info._1
  val height = info._2
  val bitsPerPixel = info._3
  val hasAlpha = bitsPerPixel == 4
  val bytes = info._4
}

object LousyScalaCompilerRasterAlternative
{
  def create(w: Int, h: Int, alpha: Boolean) : WritableRaster =
  {
    val bands = if (alpha) 4 else 3
    val bandOffsets: Array[Int] = (for (i <- 0 until bands) yield i).toArray
    val scanlineStride = w * bands
    val pixelStride = bands
    
    var maxBandOff = bandOffsets(0)
    for (o <- bandOffsets)
      if (o > maxBandOff) maxBandOff = o
    
    val size = maxBandOff + scanlineStride * (h - 1) + pixelStride * (w - 1) + 1
    val dataBuffer = new DataBufferByte(size)
    val location = new Point(0, 0)
    val csm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, w, h, pixelStride, scanlineStride, bandOffsets)
    
    new ByteInterleavedRaster(csm, dataBuffer, location)
  }
}
